package com.muyan.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期工具类
 *
 * @author zzl
 * @since 1.0 2018/03/19
 */
public class DateUtil {

    public static final String DF_1 = "yyyy-MM-dd";
    public static final String DF_2 = "yyyy-MM-dd HH:mm:ss";
    public static final String DF_3 = "yyyyMMdd";
    public static final String DF_4 = "MM-dd HH:mm";
    public static final String DF_5 = "yyyyMMddHHmmssSSS";

    /**
     * 获取指定 年，月，日的日期，日以下时间单位都是0
     * month 从1开始 1-12
     */
    public static Date getDate(int year, int month, int day) {
        Calendar c = new GregorianCalendar(year, month - 1, day);
        return c.getTime();
    }

    /**
     * 自定日期字段值
     */
    public static Date getDateSetField(Date target, int fieldValue, int num) {
        Calendar c = Calendar.getInstance();
        c.setTime(target);
        c.set(fieldValue, num);
        return c.getTime();
    }

    /**
     * 获取昨天的日期，时分秒毫秒都为0
     */
    public static Date getYesterday() {
        Calendar c = getCurrentCalendar(0, 0, 0);
        c.add(Calendar.DAY_OF_MONTH, -1);
        return c.getTime();
    }

    /**
     * 获取今日日期 ，时分秒毫秒都为0
     */
    public static Date getToday() {
        return getCurrentDate(0, 0, 0);
    }

    /**
     * 根据时间戳判断是否是今天
     */
    public static Boolean isToday(Long mills) {
        String frontDay = toStr(new Date(mills), DF_1);
        String today = toStr(new Date(), DF_1);//今天的时间
        return frontDay.equals(today);
    }

    /**
     * 获取明天的日期，时分秒为0
     */
    public static Date getTomorrow() {
        Calendar c = getCurrentCalendar(0, 0, 0);
        c.add(Calendar.DAY_OF_MONTH, 1);
        return c.getTime();
    }

    /**
     * 获取指定日期的某个字段值
     */
    public static int getFieldValue(Date src, int calendarField) {
        Calendar c = Calendar.getInstance();
        c.setTime(src);
        return c.get(calendarField);
    }

    /**
     * 增加或减少日期字段值
     */
    public static Date add(Date tar, int fieldName, int num) {
        Calendar c = Calendar.getInstance();
        c.setTime(tar);
        c.add(fieldName, num);
        return c.getTime();
    }

    /**
     * 增加或减少天数
     */
    public static Date addDay(Date tar, int num) {
        return add(tar, Calendar.DAY_OF_MONTH, num);
    }

    /**
     * 设置当前日期日历的时分秒
     */
    public static Calendar getCurrentCalendar(int hour, int minute, int second) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, hour);
        c.set(Calendar.MINUTE, minute);
        c.set(Calendar.SECOND, second);
        c.set(Calendar.MILLISECOND, 0);
        return c;
    }

    /**
     * 设置当前日期时间的时分秒
     */
    public static Date getCurrentDate(int hour, int minute, int second) {
        return getCurrentCalendar(hour, minute, second).getTime();
    }

    /**
     * 计算日期距离今天的天数
     */
    public static Integer getSubDay(Date date) {
        return getSubDay(date, new Date());
    }

    /**
     * 计算两个日期相差的天数，包括结束日期的当天
     * 例如：2019-04-18至2019-04-20，计3天
     */
    public static Integer getSubDay(Date d1, Date d2) {
        long dayMs = Math.abs(d1.getTime() - d2.getTime());
        long oneDayMs = 24 * 3600_000;
        int day = (int) (dayMs / oneDayMs);
        return day + 1;
    }

    /**
     * 获取指定格式的日期字符串
     */
    public static String toStr(Date date, String format) {
        if (date == null) {
            return "";
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat();
        dateFormat.applyPattern(format);
        return dateFormat.format(date);
    }

    /**
     * 获取 yyyy-MM-dd 格式的日期字符串
     */
    public static String toStrDay(Date date) {
        return toStr(date, DF_1);
    }

    /**
     * 获取 yyyy-MM-dd HH:mm:ss 格式的日期字符串
     */
    public static String toStrTime(Date date) {
        return toStr(date, DF_2);
    }

    /**
     * 根据指定格式的字符串获取日期
     */
    public static Date fromStr(String dateStr, String format) {
        if (dateStr == null) return null;
        SimpleDateFormat df = new SimpleDateFormat();
        df.applyPattern(format);
        try {
            return df.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据 yyyy-MM-dd 格式的字符串获取日期
     */
    public static Date fromStrDay(String dateStr) {
        return fromStr(dateStr, DF_1);
    }

    /**
     * 根据 yyyy-MM-dd HH:mm:ss 格式的字符串获取日期
     */
    public static Date fromStrTime(String dateStr) {
        return fromStr(dateStr, DF_2);
    }

    /**
     * 取两个日期中较大的
     */
    public static Date maxDate(Date d1, Date d2) {
        return d1 == null ? d2 : (d1.before(d2) ? d2 : d1);
    }

    /**
     * 取两个日期中较小的
     */
    public static Date minDate(Date d1, Date d2) {
        return d1 == null ? d2 : (d1.before(d2) ? d1 : d2);
    }

    /**
     * 计算到当天午夜的毫秒值差值
     */
    public static long getMillsToMidNight() {
        return getMillsToSomeDay(1);
    }

    /**
     * 计算当天到某天的毫秒值差值
     */
    public static long getMillsToSomeDay(int daysDelta) {
        long t1 = System.currentTimeMillis();

        Calendar c = Calendar.getInstance();
        c.add(Calendar.DATE, daysDelta);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        long t2 = c.getTimeInMillis();
        return t2 - t1;
    }

    /**
     * 根据时间戳获取此日期的0点0时0分
     */
    public static Date getBeginTime(Long mills) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(mills);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * 获取此日期的0点0时0分
     */
    public static Date getBeginTime(Date date) {
        return getBeginTime(date.getTime());
    }

    /**
     * 根据时间戳获取此日期当天的结束时间，比如 23:59:59.999
     */
    public static Date getEndTime(Long mills) {
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(mills);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * 获取此日期当天的结束时间，比如 23:59:59.999
     */
    public static Date getEndTime(Date date) {
        return getEndTime(date.getTime());
    }

}
